/**
 * WebSocket连接管理器 - 优化版本
 */

import { memoryManager, performanceMonitor } from './performance.js';

export class WebSocketManager {
  constructor(options = {}) {
    this.options = {
      url: '',
      protocols: [],
      reconnectInterval: 3000,      // 重连间隔
      maxReconnectAttempts: 5,      // 最大重连次数
      heartbeatInterval: 30000,     // 心跳间隔
      heartbeatTimeout: 5000,       // 心跳超时
      messageQueueSize: 100,        // 消息队列大小
      enableCompression: true,      // 启用压缩
      enableBatchSend: true,        // 启用批量发送
      batchSendInterval: 100,       // 批量发送间隔
      enableRetry: true,            // 启用重试
      maxRetryAttempts: 3,          // 最大重试次数
      retryDelay: 1000,             // 重试延迟
      ...options
    };
    
    this.ws = null;
    this.status = 'disconnected'; // disconnected, connecting, connected, reconnecting
    this.reconnectAttempts = 0;
    this.heartbeatTimer = null;
    this.heartbeatTimeoutTimer = null;
    this.messageQueue = [];
    this.batchSendTimer = null;
    this.retryQueue = new Map();
    this.listeners = new Map();
    this.isDestroyed = false;
    
    this.init();
  }
  
  // 初始化
  init() {
    this.connect();
    this.startHeartbeat();
  }
  
  // 连接WebSocket
  connect() {
    if (this.isDestroyed) return;
    
    try {
      this.status = 'connecting';
      this.emit('statusChange', this.status);
      
      this.ws = new WebSocket(this.options.url, this.options.protocols);
      
      this.ws.onopen = this.handleOpen.bind(this);
      this.ws.onmessage = this.handleMessage.bind(this);
      this.ws.onclose = this.handleClose.bind(this);
      this.ws.onerror = this.handleError.bind(this);
      
    } catch (error) {
      console.error('WebSocket connection error:', error);
      this.handleError(error);
    }
  }
  
  // 处理连接打开
  handleOpen(event) {
    console.log('WebSocket connected');
    this.status = 'connected';
    this.reconnectAttempts = 0;
    this.emit('open', event);
    this.emit('statusChange', this.status);
    
    // 发送队列中的消息
    this.flushMessageQueue();
    
    // 重试失败的消息
    this.retryFailedMessages();
  }
  
  // 处理消息接收
  handleMessage(event) {
    try {
      let data = event.data;
      
      // 解压缩消息
      if (this.options.enableCompression) {
        data = this.decompressMessage(data);
      }
      
      // 解析消息
      const message = JSON.parse(data);
      
      // 性能监控
      performanceMonitor.incrementCounter('websocketMessages');
      
      // 触发消息事件
      this.emit('message', message);
      
      // 触发特定类型消息事件
      if (message.type) {
        this.emit(`message:${message.type}`, message);
      }
      
    } catch (error) {
      console.error('WebSocket message parse error:', error);
      this.emit('error', error);
    }
  }
  
  // 处理连接关闭
  handleClose(event) {
    console.log('WebSocket disconnected:', event.code, event.reason);
    this.status = 'disconnected';
    this.emit('close', event);
    this.emit('statusChange', this.status);
    
    // 清理定时器
    this.clearHeartbeat();
    
    // 尝试重连
    if (!this.isDestroyed && this.reconnectAttempts < this.options.maxReconnectAttempts) {
      this.reconnect();
    }
  }
  
  // 处理错误
  handleError(error) {
    console.error('WebSocket error:', error);
    this.emit('error', error);
    
    // 如果连接失败，尝试重连
    if (this.status === 'connecting' && !this.isDestroyed) {
      setTimeout(() => {
        this.reconnect();
      }, this.options.reconnectInterval);
    }
  }
  
  // 重连
  reconnect() {
    if (this.isDestroyed) return;
    
    this.status = 'reconnecting';
    this.reconnectAttempts++;
    this.emit('statusChange', this.status);
    
    console.log(`WebSocket reconnecting... (${this.reconnectAttempts}/${this.options.maxReconnectAttempts})`);
    
    setTimeout(() => {
      this.connect();
    }, this.options.reconnectInterval);
  }
  
  // 发送消息
  send(message, options = {}) {
    if (this.status !== 'connected') {
      // 如果未连接，将消息加入队列
      if (this.messageQueue.length < this.options.messageQueueSize) {
        this.messageQueue.push({ message, options, timestamp: Date.now() });
      }
      return false;
    }
    
    try {
      let data = message;
      
      // 序列化消息
      if (typeof message !== 'string') {
        data = JSON.stringify(message);
      }
      
      // 压缩消息
      if (this.options.enableCompression) {
        data = this.compressMessage(data);
      }
      
      // 批量发送
      if (this.options.enableBatchSend && !options.urgent) {
        this.addToBatch(data, options);
        return true;
      }
      
      // 直接发送
      this.ws.send(data);
      performanceMonitor.incrementCounter('websocketSent');
      return true;
      
    } catch (error) {
      console.error('WebSocket send error:', error);
      this.handleSendError(message, options, error);
      return false;
    }
  }
  
  // 添加到批量发送队列
  addToBatch(data, options) {
    this.messageQueue.push({ data, options, timestamp: Date.now() });
    
    if (!this.batchSendTimer) {
      this.batchSendTimer = setTimeout(() => {
        this.flushBatch();
      }, this.options.batchSendInterval);
    }
  }
  
  // 刷新批量发送
  flushBatch() {
    if (this.messageQueue.length === 0) return;
    
    const messages = this.messageQueue.splice(0);
    const batchData = {
      type: 'batch',
      messages: messages.map(item => item.data),
      timestamp: Date.now()
    };
    
    try {
      this.ws.send(JSON.stringify(batchData));
      performanceMonitor.incrementCounter('websocketSent');
    } catch (error) {
      console.error('WebSocket batch send error:', error);
      // 重新加入队列
      this.messageQueue.unshift(...messages);
    }
    
    this.batchSendTimer = null;
  }
  
  // 刷新消息队列
  flushMessageQueue() {
    if (this.messageQueue.length === 0) return;
    
    const messages = this.messageQueue.splice(0);
    messages.forEach(({ message, options }) => {
      this.send(message, options);
    });
  }
  
  // 处理发送错误
  handleSendError(message, options, error) {
    if (this.options.enableRetry && options.retry !== false) {
      const retryKey = `${Date.now()}_${Math.random()}`;
      this.retryQueue.set(retryKey, {
        message,
        options: { ...options, retryCount: (options.retryCount || 0) + 1 },
        timestamp: Date.now()
      });
      
      // 延迟重试
      setTimeout(() => {
        this.retryMessage(retryKey);
      }, this.options.retryDelay);
    }
    
    this.emit('sendError', { message, error });
  }
  
  // 重试消息
  retryMessage(retryKey) {
    const retryItem = this.retryQueue.get(retryKey);
    if (!retryItem) return;
    
    const { message, options } = retryItem;
    
    if (options.retryCount >= this.options.maxRetryAttempts) {
      this.retryQueue.delete(retryKey);
      this.emit('retryFailed', { message, options });
      return;
    }
    
    if (this.send(message, options)) {
      this.retryQueue.delete(retryKey);
    }
  }
  
  // 重试失败的消息
  retryFailedMessages() {
    for (const [key, retryItem] of this.retryQueue.entries()) {
      this.retryMessage(key);
    }
  }
  
  // 开始心跳
  startHeartbeat() {
    if (this.heartbeatTimer) return;
    
    this.heartbeatTimer = setInterval(() => {
      if (this.status === 'connected') {
        this.sendHeartbeat();
      }
    }, this.options.heartbeatInterval);
  }
  
  // 发送心跳
  sendHeartbeat() {
    const heartbeat = {
      type: 'heartbeat',
      timestamp: Date.now()
    };
    
    this.send(heartbeat, { urgent: true });
    
    // 设置心跳超时
    this.heartbeatTimeoutTimer = setTimeout(() => {
      console.warn('WebSocket heartbeat timeout');
      this.close();
    }, this.options.heartbeatTimeout);
  }
  
  // 清理心跳
  clearHeartbeat() {
    if (this.heartbeatTimer) {
      clearInterval(this.heartbeatTimer);
      this.heartbeatTimer = null;
    }
    
    if (this.heartbeatTimeoutTimer) {
      clearTimeout(this.heartbeatTimeoutTimer);
      this.heartbeatTimeoutTimer = null;
    }
  }
  
  // 压缩消息
  compressMessage(data) {
    // 简单的压缩实现，实际项目中可以使用更高效的压缩算法
    if (data.length > 1024) {
      return `compressed:${btoa(data)}`;
    }
    return data;
  }
  
  // 解压缩消息
  decompressMessage(data) {
    if (typeof data === 'string' && data.startsWith('compressed:')) {
      return atob(data.substring(11));
    }
    return data;
  }
  
  // 添加事件监听器
  on(event, callback) {
    if (!this.listeners.has(event)) {
      this.listeners.set(event, []);
    }
    this.listeners.get(event).push(callback);
  }
  
  // 移除事件监听器
  off(event, callback) {
    if (!this.listeners.has(event)) return;
    
    const callbacks = this.listeners.get(event);
    const index = callbacks.indexOf(callback);
    if (index > -1) {
      callbacks.splice(index, 1);
    }
  }
  
  // 触发事件
  emit(event, data) {
    if (!this.listeners.has(event)) return;
    
    const callbacks = this.listeners.get(event);
    callbacks.forEach(callback => {
      try {
        callback(data);
      } catch (error) {
        console.error('WebSocket event handler error:', error);
      }
    });
  }
  
  // 关闭连接
  close(code = 1000, reason = 'Normal closure') {
    this.isDestroyed = true;
    this.clearHeartbeat();
    
    if (this.batchSendTimer) {
      clearTimeout(this.batchSendTimer);
      this.batchSendTimer = null;
    }
    
    if (this.ws && this.ws.readyState === WebSocket.OPEN) {
      this.ws.close(code, reason);
    }
    
    this.status = 'disconnected';
    this.emit('statusChange', this.status);
  }
  
  // 获取连接状态
  getStatus() {
    return {
      status: this.status,
      reconnectAttempts: this.reconnectAttempts,
      queueSize: this.messageQueue.length,
      retryQueueSize: this.retryQueue.size,
      isConnected: this.status === 'connected'
    };
  }
  
  // 获取统计信息
  getStats() {
    return {
      status: this.status,
      reconnectAttempts: this.reconnectAttempts,
      queueSize: this.messageQueue.length,
      retryQueueSize: this.retryQueue.size,
      isConnected: this.status === 'connected',
      options: this.options
    };
  }
}

// WebSocket连接池管理器
export class WebSocketPool {
  constructor(options = {}) {
    this.options = {
      maxConnections: 5,
      connectionTimeout: 10000,
      ...options
    };
    
    this.connections = new Map();
    this.connectionQueue = [];
  }
  
  // 获取连接
  getConnection(key, options = {}) {
    if (this.connections.has(key)) {
      return this.connections.get(key);
    }
    
    if (this.connections.size >= this.options.maxConnections) {
      // 连接池已满，加入队列
      return new Promise((resolve) => {
        this.connectionQueue.push({ key, options, resolve });
      });
    }
    
    const connection = new WebSocketManager(options);
    this.connections.set(key, connection);
    
    connection.on('close', () => {
      this.connections.delete(key);
      this.processQueue();
    });
    
    return connection;
  }
  
  // 处理队列
  processQueue() {
    if (this.connectionQueue.length === 0) return;
    
    const { key, options, resolve } = this.connectionQueue.shift();
    const connection = this.getConnection(key, options);
    resolve(connection);
  }
  
  // 关闭所有连接
  closeAll() {
    for (const connection of this.connections.values()) {
      connection.close();
    }
    this.connections.clear();
    this.connectionQueue = [];
  }
}

// 导出单例实例
export const websocketManager = new WebSocketManager();
export const websocketPool = new WebSocketPool();

// 全局注册
if (typeof window !== 'undefined') {
  window.websocketManager = websocketManager;
  window.websocketPool = websocketPool;
}
